use clap::arg;
use clap::Args;
use fudata::db;
use fudata::model::kline::Klt;
use log::debug;
use log::error;
use log::info;
use tokio::select;
use anyhow::Result;
use anyhow::anyhow;

use crate::cli::commands::register_ctrl_c;
use crate::cli::commands::wait_until_next_scheduled_time;
use crate::todo::worker_sse;
use crate::todo::MAX_WORKERS;

#[derive(Args, Debug)]
pub struct SseCommandArguments {
    #[arg(
        help = "Database path used for storing data",
        short = 'p',
        long = "path",
        requires = "path",
        default_value = "memory"
    )]
    pub path: String,

    #[arg(
        help = "settings to craw securities",
        short = 's',
        long = "settings",
        default_value = "./config.toml"
    )]
    /// settings in toml format, e.g. config.toml
    pub settings: String,
}

pub async fn init(SseCommandArguments { path, settings, .. }: SseCommandArguments) -> Result<()> {
    let dbrs = db::init().await;
    match dbrs {
        Ok(_) => {}
        Err(e) => {
            return Err(anyhow!(e));
        }
    }

    info!("Starting fudacraw sse...");

    debug!("(sse::init) arguments: path= {}", path);
    debug!("(sse::init) arguments: settings=  {}", settings);

    // Listen for Ctrl-C signal
    let shutdown_rx_arc = register_ctrl_c();
    let sse_todo_injector = worker_sse::start_todo_worker_pool(MAX_WORKERS);
    loop {
        // Wrap the receiver in a cloneable Arc<Mutex<_>> to allow concurrent access
        let mut shutdown_rx_locked = shutdown_rx_arc.lock().await;

        select!(
            _ = shutdown_rx_locked.recv()  => {
                info!("Shutting down from signal handler");
                break;
            }

            gen_sse_todos_next_time = wait_until_next_scheduled_time("0/10 * * * * * 2030" ,"gen_sse_todos_next_time")=>{
                info!("\n gen_sse_todos_next_time scheduled time: {:?} ", gen_sse_todos_next_time );
                let _ = worker_sse::generate_sse_todos().await;
            }

            get_sse_todos_next_time = wait_until_next_scheduled_time("0 0/1 * * * *","get_sse_todos_next_time" )=>{
                info!("\n worker_sse scheduled time: {:?} ", get_sse_todos_next_time );
                let rs = worker_sse::get_oldest_sse_todos().await;
                match rs{
                    Ok(todos) => {
                        for todo in todos{
                            let _ = sse_todo_injector.0.push(todo);
                        }
                    },
                    Err(e) => error!("(crawl::get_oldest_sse_todos){:?}",e),
                }
            }

            refresh_kline_with_ticks_next_time = wait_until_next_scheduled_time("0 0/5 * * * Mon,Tue,Wed,Thu,Fri","refresh_kline_with_ticks_next_time" )=>{
                info!("\n refresh_minutes_kline_with_ticks scheduled time: {:?} ", refresh_kline_with_ticks_next_time );
                let _ = worker_sse::refresh_kline_with_ticks( ).await;
            }
       
        );
    }

    // All ok
    Ok(())
}
